﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace DockSample
{
    public partial class TraceDialog :Form
    {
        //
        private static TraceDialog singletonTraceDialog = new TraceDialog();
        //
        private HighOrderObjectDiagram tracedDiagram;
        TreeNode decompNode = null;
        TreeNode partnerNode = null;
        //
        private TraceDialog()
        {
            InitializeComponent();
            //此分析窗口总是显示在其他窗口的前面
            this.TopMost = true;
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
            this.MaximizeBox = false;
            
        }
        //单例模式取出对象
        public static TraceDialog getInstanceOfTraceDialog(HighOrderObjectDiagram diagram)
        {
            singletonTraceDialog.tracedDiagram = diagram;
            singletonTraceDialog.initTraceDialog();
            return singletonTraceDialog;
        }
        //
        //初始化
        private void initTraceDialog()
        {
            clearTraceDialog();
            initObjectToolStripMenuItem();
            initAttributeToolStripMenuItem();
            initMethodToolStripMenuItem();
        }
        //
        private void clearTraceDialog()
        {
            this.objectToolStripMenuItem.DropDownItems.Clear();
            this.attributeToolStripMenuItem.DropDownItems.Clear();
            this.methodToolStripMenuItem.DropDownItems.Clear();
            this.traceTreeView.Nodes.Clear();
        }
        //
        private void initObjectToolStripMenuItem()
        {
            ToolStripMenuItem ObjectMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            ObjectMenuItem.Name = tracedDiagram.Name;
            ObjectMenuItem.Size = new System.Drawing.Size(202, 22);
            ObjectMenuItem.Text = tracedDiagram.Name;
            ObjectMenuItem.Click += new System.EventHandler(this.objectMenuItem_Click);

            this.objectToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {ObjectMenuItem});
        }
        //
        private void initAttributeToolStripMenuItem()
        {
            foreach (Attribute attr in tracedDiagram.AttributeList)
            {
                ToolStripMenuItem attrMenuItem = new System.Windows.Forms.ToolStripMenuItem();
                attrMenuItem.Name = attr.AttributeName;
                attrMenuItem.Size = new System.Drawing.Size(202, 22);
                attrMenuItem.Text = attr.AttributeName;
                attrMenuItem.Click += new System.EventHandler(this.attrMenuItem_Click);
                this.attributeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { attrMenuItem });
            }
        }
        //
        private void initMethodToolStripMenuItem()
        {
            foreach (Method method in this.tracedDiagram.MethodList)
            {
                ToolStripMenuItem methodMenuItem = new System.Windows.Forms.ToolStripMenuItem();
                methodMenuItem.Name = method.MethodName;
                methodMenuItem.Size = new System.Drawing.Size(202, 22);
                methodMenuItem.Text = method.MethodName;
                methodMenuItem.Click += new System.EventHandler(this.methodMenuItem_Click);
                this.methodToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { methodMenuItem });
            }
        }
        //
        //事件响应函数
        private void objectMenuItem_Click(object sender, EventArgs e)
        {
            this.traceTreeView.Nodes.Clear();
            this.traceTreeView.ContextMenuStrip = this.objectTraceContextMenuStrip;

            //根节点.Decomposition
            decompNode = new TreeNode(tracedDiagram.Name + "(Decomposition)");
            decompNode.Tag = this.tracedDiagram;
            this.traceTreeView.Nodes.Add(decompNode);

            //根节点.Partner
            partnerNode = new TreeNode(tracedDiagram.Name + "(Partner)");
            partnerNode.Tag = this.tracedDiagram;
            this.traceTreeView.Nodes.Add(partnerNode);

            //跟踪此图形的分解
            traceObject(this.tracedDiagram, this.decompNode, this.partnerNode, false);
            this.traceTreeView.ExpandAll();
        }
        //
        private void attrMenuItem_Click(object sender, EventArgs e)
        {
            this.traceTreeView.Nodes.Clear();
            this.traceTreeView.ContextMenuStrip = attrTraceContextMenuStrip;

            if (sender is ToolStripMenuItem)
            {
                ToolStripMenuItem attrName = (ToolStripMenuItem)sender;

                foreach (Attribute attr in this.tracedDiagram.AttributeList)
                {
                    if(attr.AttributeName.Equals(attrName.Name))
                    {
                        decompNode = new TreeNode(tracedDiagram.Name + "." + attr.AttributeName);
                        decompNode.Tag = attr;

                        this.traceTreeView.Nodes.Add(decompNode);
                        //跟踪选中的属性
                        if (this.tracedDiagram.HasModelForm)
                        {
                            traceAttr(attr, this.tracedDiagram, decompNode, false);
                        }
                        this.traceTreeView.ExpandAll();

                        break;
                    }
                }
            }
        }
        //
        private void methodMenuItem_Click(object sender, EventArgs e)
        {
            this.traceTreeView.Nodes.Clear();
            this.traceTreeView.ContextMenuStrip = methodtraceContextMenuStrip;

            if (sender is ToolStripMenuItem)
            {
                ToolStripMenuItem methodName = (ToolStripMenuItem)sender;

                foreach (Method method in tracedDiagram.MethodList)
                {
                    if (method.MethodName.Equals(methodName.Name))
                    {
                        decompNode = new TreeNode(tracedDiagram.Name + "." + method.MethodName);
                        decompNode.Tag = method;

                        this.traceTreeView.Nodes.Add(decompNode);
                        if (this.tracedDiagram.HasModelForm)
                        {
                            traceMethod(method, this.tracedDiagram, decompNode, false);
                        }
                        this.traceTreeView.ExpandAll();
                        break;
                    }
                }
            }
        }
        //
        private void nFRToolStripMenuItem_Click(object sender, EventArgs e)
        {
            NFRTraceSelector selector = new NFRTraceSelector(this.tracedDiagram);
            if (selector.ShowDialog() == DialogResult.OK)
            {
                //根据selector收集到的信息跟踪具体的NFR
                string entityType = selector.EntityType;
                string entityTarget = selector.EntityTarget;
                string NFRName = selector.NFRName;
                if (entityType.Equals("Object"))
                {
                    traceObjectNFR(NFRName);
                }
                else if (entityType.Equals("Attribute"))
                {
                    traceAttrNFR(NFRName, entityTarget);
                }
                else if (entityType.Equals("Method"))
                {
                    traceMethodNFR(NFRName, entityTarget);
                }
                else
                {
                    MessageBox.Show("Internal Error ---nFRToolStripMenuItem_Click()");
                }
            }
        }
        //
        //跟踪对象or对象NFR的具体实现函数
        private void traceObject(HighOrderObjectDiagram diagram, TreeNode upLevelNode, TreeNode upLevelPartnerNode, bool traceNFR, string NFRName = "")
        {
            if (diagram.HasModelForm)
            {
                foreach (ObjectDiagram diag in diagram.NewModelForm.diagramList)
                {
                    //若子类没有实现父类的NFR，则认为此NFR的值为NULL
                    /*TreeNode newNode = new TreeNode(NFRName + ":" + " null " + "[" + diag.Name + "]");
                    //跟踪非功能
                    if (traceNFR)
                    {
                        foreach (NonFunctionRequirment NFR in diag.ObjectNFRList)
                        {
                            if (NFR.NonFunctionName.Equals(NFRName))
                            {
                                newNode = new TreeNode(NFR.NonFunctionName + ":" + NFR.NonFunctionValue + "[" + diag.Name + "]");
                                break;
                            }
                        }
                    }
                    else*/
                    TreeNode newNode = new TreeNode(diag.Name);
                    
                    //添加节点
                    if (diag is ExternalInterfaceIn || diag is ExternalInterfaceOut)
                    {
                        addObjectNodeToTraceTreeView(diag, newNode, upLevelPartnerNode);
                    }
                    else if (diag is HighOrderObjectDiagram&&((HighOrderObjectDiagram)diag).HasModelForm)
                    {
                        newNode.Text = diag.Name + "(Decomposition)";
                        addObjectNodeToTraceTreeView(diag, newNode, upLevelNode);
                        //递归添加节点
                        TreeNode partnerNode = new TreeNode(diag.Name + "(Partner)");
                        addObjectNodeToTraceTreeView(diag, partnerNode, upLevelNode);
                        traceObject((HighOrderObjectDiagram)diag, newNode, partnerNode, traceNFR, NFRName);
                    }
                    else
                    {
                        addObjectNodeToTraceTreeView(diag, newNode, upLevelNode);
                    }
                }
            }
        }
        //
        private void traceObjectNFR(HighOrderObjectDiagram diagram, TreeNode upLevelNode, string NFRName)
        {
            if (diagram.HasModelForm)
            {
                foreach (ObjectDiagram diag in diagram.NewModelForm.diagramList)
                {
                    //若子类没有实现父类的NFR，则认为此NFR的值为NULL
                    //TreeNode newNode = new TreeNode(NFRName + ":" + " null " + "[" + diag.Name + "]");
                    //跟踪非功能
                    foreach (NonFunctionRequirment NFR in diag.ObjectNFRList)
                    {
                        if (NFR.NonFunctionName.Equals(NFRName))
                        {
                            TreeNode newNode = new TreeNode(diag.Name + "." + NFR.NonFunctionName + ":" + NFR.NonFunctionValue);
                            addObjectNodeToTraceTreeView(diag, newNode, upLevelNode);
                            //
                            if (diag is HighOrderObjectDiagram && ((HighOrderObjectDiagram)diag).HasModelForm)
                            {
                                traceObjectNFR((HighOrderObjectDiagram)diag, newNode, NFRName);
                            }
                            break;
                        }
                    }
                }
            }
        }
        //
        private void addObjectNodeToTraceTreeView(ObjectDiagram diag, TreeNode newNode, TreeNode upLevelNode)
        {
            newNode.Tag = diag;
            upLevelNode.Nodes.Add(newNode);
        }
        //跟踪属性or属性NFR的具体实现函数
        private void traceAttr(Attribute attr, HighOrderObjectDiagram diagram, TreeNode upLevelNode, bool traceNFR, string NFRName = "")
        {
            foreach (ObjectDiagram diag in diagram.NewModelForm.diagramList)
            {
                foreach (Attribute newAttr in diag.AttributeList)
                {
                    if (attr.id.Equals(newAttr.parentAttrId))
                    {
                        TreeNode newNode = new TreeNode(diag.Name + "." + newAttr.AttributeName + "."+ NFRName + ":" + " null " );
                        if (traceNFR)
                        {
                            foreach (NonFunctionRequirment NFR in newAttr.AttributeNFRList)
                            {
                                if (NFR.NonFunctionName.Equals(NFRName))
                                {
                                    newNode = new TreeNode(diag.Name + "." + newAttr.AttributeName + "." + NFRName + ":" + newAttr.AttributeName);
                                    break;
                                }
                            }
                        }
                        else
                        {
                            newNode = new TreeNode(diag.Name + "." + newAttr.AttributeName);
                        }

                        addAttrNodeToTraceTreeView(newAttr, newNode, upLevelNode);

                        if (diag is HighOrderObjectDiagram && ((HighOrderObjectDiagram)diag).HasModelForm)
                        {
                            traceAttr(newAttr, (HighOrderObjectDiagram)diag, newNode, traceNFR, NFRName);
                        }
                    }
                }
            }
        }
        //
        private void addAttrNodeToTraceTreeView(Attribute newAttr, TreeNode newNode, TreeNode upLevelNode)
        {
            newNode.Tag = newAttr;
            upLevelNode.Nodes.Add(newNode);
        }
        //跟踪方法or方法NFR的具体实现函数
        private void traceMethod(Method method, HighOrderObjectDiagram diagram, TreeNode upLevelNode, bool traceNFR, string NFRName = "")
        {
            foreach (ObjectDiagram diag in diagram.NewModelForm.diagramList)
            {
                foreach (Method newMethod in diag.MethodList)
                {
                    if (method.id.Equals(newMethod.parentMethodId))
                    {
                        TreeNode newNode = new TreeNode(diag.Name + "." + newMethod.MethodName + "."+NFRName + ":" + " null " );
                        if (traceNFR)
                        {
                            foreach (NonFunctionRequirment NFR in newMethod.MethodNFRList)
                            {
                                if (NFR.NonFunctionName.Equals(NFRName))
                                {
                                    newNode = new TreeNode(diag.Name + "." + newMethod.MethodName + "." + NFRName + ":" + NFR.NonFunctionValue);
                                    break;
                                }
                            }
                        }
                        else
                        {
                            newNode = new TreeNode(diag.Name + "." + newMethod.MethodName);
                        }

                        addMethodNodeToTraceTreeNode(newMethod, newNode, upLevelNode);

                        if (diag is HighOrderObjectDiagram && ((HighOrderObjectDiagram)diag).HasModelForm)
                        {
                            traceMethod(newMethod, (HighOrderObjectDiagram)diag, newNode, traceNFR, NFRName);
                        }
                    }
                }

            }
        }
        //
        private void addMethodNodeToTraceTreeNode(Method newMethod, TreeNode newNode, TreeNode upLevelNode)
        {
            newNode.Tag = newMethod;
            upLevelNode.Nodes.Add(newNode);
        }
        //跟踪对象NFR
        private void traceObjectNFR(string NFRName)
        {
            this.traceTreeView.Nodes.Clear();
            this.traceTreeView.ContextMenuStrip = objectTraceContextMenuStrip;
            //根节点
            foreach (NonFunctionRequirment NFR in tracedDiagram.ObjectNFRList)
            {
                if(NFR.NonFunctionName.Equals(NFRName))
                {
                    decompNode = new TreeNode(tracedDiagram.Name + "." + NFR.NonFunctionName + ":" + NFR.NonFunctionValue);
                    decompNode.Tag = this.tracedDiagram;
                    this.traceTreeView.Nodes.Add(decompNode);
                    //跟踪此图形的分解
                    traceObjectNFR(this.tracedDiagram, this.decompNode,NFRName);
                    break;
                }
            }
            
            this.traceTreeView.ExpandAll();
        }
        //跟踪属性NFR
        private void traceAttrNFR(string NFRName, string attrName)
        {
            this.traceTreeView.Nodes.Clear();
            this.traceTreeView.ContextMenuStrip = this.attrTraceContextMenuStrip;

            foreach (Attribute attr in this.tracedDiagram.AttributeList)
            {
                if (attr.AttributeName.Equals(attrName))
                {
                    decompNode = new TreeNode(attr.AttributeName);

                    foreach (NonFunctionRequirment NFR in attr.AttributeNFRList)
                    {
                        if (NFR.NonFunctionName.Equals(NFRName))
                        {
                            decompNode = new TreeNode(tracedDiagram.Name + "." + attr.AttributeName + "." + NFR.NonFunctionName + ":" + NFR.NonFunctionValue);
                            break;
                        }
                    }
                    decompNode.Tag = attr;
                    this.traceTreeView.Nodes.Add(decompNode);

                    if (this.tracedDiagram.HasModelForm)
                    {
                        //递归跟踪
                        traceAttr(attr, this.tracedDiagram, decompNode, true, NFRName);
                    }

                    this.traceTreeView.ExpandAll();
                    break;
                }
            }
        }
        //跟踪方法NFR
        private void traceMethodNFR(string NFRName, string methodName)
        {
            this.traceTreeView.Nodes.Clear();
            this.traceTreeView.ContextMenuStrip = this.methodtraceContextMenuStrip;
            foreach (Method method in tracedDiagram.MethodList)
            {
                if (method.MethodName.Equals(methodName))
                {
                    decompNode = new TreeNode(method.MethodName);
                    foreach (NonFunctionRequirment NFR in method.MethodNFRList)
                    {
                        if (NFR.NonFunctionName.Equals(NFRName))
                        {
                            decompNode = new TreeNode(tracedDiagram.Name + "." + method.MethodName + "."+ NFR.NonFunctionName + ":" + NFR.NonFunctionValue);
                            break;
                        }
                    }
                    decompNode.Tag = method;
                    this.traceTreeView.Nodes.Add(decompNode);

                    if (this.tracedDiagram.HasModelForm)
                    {
                        //递归跟踪
                        traceMethod(method, this.tracedDiagram, decompNode, true, NFRName);
                    }

                    this.traceTreeView.ExpandAll();
                    break;
                }
            }
        }
        //
        //traceTreeView的三种弹出菜单响应函数
        private void showDiagramObjectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OriginalDiagram diagram = (OriginalDiagram)this.traceTreeView.SelectedNode.Tag;
            DummyModelForm form = InquiryUtil.getOriginalModelFormByDiagram(diagram);

            diagram.IsSelected = true;
            form.BringToFront();
            form.Focus();
        }
        //
        private void showDiagramMethodToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DummyModelForm form = InquiryUtil.getOriginalModelFormByMethod((Method)this.traceTreeView.SelectedNode.Tag);
            form.BringToFront();
            form.Focus();
        }
        //
        private void showDiagramAttrToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DummyModelForm form = InquiryUtil.getOriginalModelFormByAttr((Attribute)this.traceTreeView.SelectedNode.Tag);
            form.BringToFront();
            form.Focus();
        }

        private void TraceDialog_Load(object sender, EventArgs e)
        {
            //控制窗口出现的位置
            this.Location = new Point(1000, 50);
        }

        private void TraceDialog_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            base.OnClosing(e);
            this.Hide();
        }
        //
        //窗体事件函数
        //protected override void ModelForm_Click(object sender, EventArgs e)
        //{
        //    this.BringToFront();
        //    this.Focus();
        //}
        ////
        //protected override void ModelForm_FormClosing(object sender, FormClosingEventArgs e)
        //{
        //    e.Cancel = true;
        //    base.OnClosing(e);
        //    this.Hide();
        //}
    }
}
